package com.zt.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.zt.config.WechatConfig;
import com.zt.domain.User;
import com.zt.dto.WechatAccessTokenDTO;
import com.zt.dto.WechatLoginDTO;
import com.zt.dto.WechatUserInfoDTO;
import com.zt.dto.WechatPhoneDTO;
import com.zt.mapper.UserMapper;
import com.zt.service.WechatLoginService;
import com.zt.utils.TokenUtils;
import com.zt.vo.WechatLoginVO;

import lombok.extern.slf4j.Slf4j;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 微信登录服务实现类1
 */
@Slf4j
@Service
public class WechatLoginServiceImpl implements WechatLoginService {

    @Autowired
    private WechatConfig wechatConfig;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 微信小程序登录
     *
     * @param loginDTO 登录参数
     * @param ip 登录IP
     * @return 登录结果
     */
    @Override
    public WechatLoginVO wechatLogin(WechatLoginDTO loginDTO, String ip) {
        log.info("微信小程序登录, code: {}, ip: {}", loginDTO.getCode(), ip);
        
        // 1. 获取微信登录凭证校验结果
        WechatAccessTokenDTO wxResult = getWxLoginInfo(loginDTO.getCode());
        if (wxResult == null || StringUtils.isEmpty(wxResult.getOpenid())) {
            throw new ServiceException("获取微信授权信息失败");
        }
        
        // 2. 检查用户是否存在，不存在则注册
        User user = userMapper.selectUserByOpenid(wxResult.getOpenid());
        if (user == null) {
            // 新用户注册
            user = createUser(wxResult, ip);
        } else {
            // 更新登录信息
            updateUserLoginInfo(user, ip);
        }
        
        // 3. 生成认证token
        String token = TokenUtils.createToken(user.getId());
        
        // 4. 返回登录结果
        return new WechatLoginVO()
                .setUser(user)
                .setToken(token);
    }
    
    /**
     * 获取微信登录凭证校验结果
     *
     * @param code 登录凭证
     * @return 校验结果
     */
    private WechatAccessTokenDTO getWxLoginInfo(String code) {
        try {
            String url = UriComponentsBuilder.fromHttpUrl(wechatConfig.getJsCode2SessionUrl())
                    .queryParam("appid", wechatConfig.getAppId())
                    .queryParam("secret", wechatConfig.getAppSecret())
                    .queryParam("js_code", code)
                    .queryParam("grant_type", wechatConfig.getGrantType())
                    .encode()
                    .build()
                    .toUriString();
            
            log.info("请求微信登录凭证校验, appid: {}, secret前6位: {}, code: {}", 
                    wechatConfig.getAppId(), 
                    wechatConfig.getAppSecret().substring(0, 6),
                    code);
            log.info("完整请求URL: {}", url);
            
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
            String responseBody = responseEntity.getBody();
            log.info("微信返回原始响应: {}", responseBody);
            
            if (responseEntity.getStatusCode() == HttpStatus.OK && responseBody != null) {
                ObjectMapper objectMapper = new ObjectMapper();
                WechatAccessTokenDTO wxResult = objectMapper.readValue(responseBody, WechatAccessTokenDTO.class);
                log.info("解析后的响应内容: {}", wxResult);
                
                if (wxResult != null && wxResult.getErrcode() != null && wxResult.getErrcode() != 0) {
                    log.error("微信登录凭证校验失败, 错误码: {}, 错误信息: {}", wxResult.getErrcode(), wxResult.getErrmsg());
                    return null;
                }
                
                return wxResult;
            }
        } catch (Exception e) {
            log.error("微信登录凭证校验失败, 错误: {}", e.getMessage(), e);
        }
        return null;
    }
    
    /**
     * 创建新用户
     *
     * @param wxResult 微信登录结果
     * @param ip 登录IP
     * @return 用户信息
     */
    private User createUser(WechatAccessTokenDTO wxResult, String ip) {
        User user = new User();
        user.setOpenid(wxResult.getOpenid());
        user.setUnionid(wxResult.getUnionid());
        user.setLastLoginIp(ip);
        user.setLastLoginAt(new Date());
        user.setStatus(1); // 默认启用
        
        userMapper.insertUser(user);
        return user;
    }
    
    /**
     * 更新用户登录信息
     *
     * @param user 当前用户
     * @param ip 登录IP
     */
    private void updateUserLoginInfo(User user, String ip) {
        userMapper.updateUserLoginInfo(user.getId(), ip);
    }

    /**
     * 获取微信手机号
     *
     * @param code 手机号获取凭证
     * @return 手机号信息
     */
    @Override
    public WechatPhoneDTO getWechatPhone(String code) {
        log.info("开始获取微信手机号, code: {}", code);
        
        try {
            String url = UriComponentsBuilder.fromHttpUrl("https://api.weixin.qq.com/wxa/business/getuserphonenumber")
                    .queryParam("access_token", getAccessToken())
                    .encode()
                    .build()
                    .toUriString();
            
            Map<String, String> requestBody = new HashMap<>();
            requestBody.put("code", code);
            
            log.info("请求微信获取手机号, URL: {}", url);
            
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestBody, String.class);
            String responseBody = responseEntity.getBody();
            log.info("微信返回原始响应: {}", responseBody);
            
            if (responseEntity.getStatusCode() == HttpStatus.OK && responseBody != null) {
                ObjectMapper objectMapper = new ObjectMapper();
                WechatPhoneDTO phoneDTO = objectMapper.readValue(responseBody, WechatPhoneDTO.class);
                log.info("解析后的响应内容: {}", phoneDTO);
                
                if (phoneDTO != null && phoneDTO.getErrcode() != null && phoneDTO.getErrcode() != 0) {
                    log.error("获取微信手机号失败, 错误码: {}, 错误信息: {}", phoneDTO.getErrcode(), phoneDTO.getErrmsg());
                    throw new ServiceException("获取手机号失败：" + phoneDTO.getErrmsg());
                }
                
                return phoneDTO;
            }
        } catch (Exception e) {
            log.error("获取微信手机号失败, 错误: {}", e.getMessage(), e);
            throw new ServiceException("获取手机号失败：" + e.getMessage());
        }
        
        throw new ServiceException("获取手机号失败");
    }

    @Override
    public Boolean updateUserInfo(User userInfo) {
        return userMapper.updateUser(userInfo) > 0;
    }

    /**
     * 获取接口调用凭据
     */
    private String getAccessToken() {
        try {
            String url = UriComponentsBuilder.fromHttpUrl("https://api.weixin.qq.com/cgi-bin/token")
                    .queryParam("grant_type", "client_credential")
                    .queryParam("appid", wechatConfig.getAppId())
                    .queryParam("secret", wechatConfig.getAppSecret())
                    .encode()
                    .build()
                    .toUriString();
            
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
            if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody() != null) {
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Object> response = objectMapper.readValue(responseEntity.getBody(), Map.class);
                
                if (response.containsKey("access_token")) {
                    return response.get("access_token").toString();
                }
            }
        } catch (Exception e) {
            log.error("获取access_token失败: {}", e.getMessage(), e);
            throw new ServiceException("获取access_token失败");
        }
        
        throw new ServiceException("获取access_token失败");
    }
} 